home *** CD-ROM | disk | FTP | other *** search
/ 17 Bit Software 6: Level 6 / 17 Bit - Level 6 (1998)(Epic Marketing)[!].iso / quartz / q0429.dms / q0429.adf / raypaint / render.c < prev    next >
C/C++ Source or Header  |  1991-08-08  |  17KB  |  699 lines

  1. /*
  2.  * render.c
  3.  *
  4.  * Copyright (C) 1989, 1991 Craig E. Kolb, Rod G. Bogart
  5.  *
  6.  * This software may be freely copied, modified, and redistributed
  7.  * provided that this copyright notice is preserved on all copies.
  8.  *
  9.  * You may not distribute this software, in whole or in part, as part of
  10.  * any commercial product without the express consent of the authors.
  11.  * 
  12.  * There is no warranty or other guarantee of fitness of this software
  13.  * for any purpose.  It is provided solely "as is".
  14.  *
  15.  * $Id: render.c,v 4.0 91/07/17 17:37:09 kolb Exp Locker: kolb $
  16.  *
  17.  * $Log:    render.c,v $
  18.  * Revision 4.0  91/07/17  17:37:09  kolb
  19.  * Initial version.
  20.  * 
  21.  */
  22.  
  23. #include "rayshade.h"
  24. #include "libcommon/sampling.h"
  25. #include "libsurf/atmosphere.h"
  26. #include "viewing.h"
  27. #include "options.h"
  28. #include "stats.h"
  29. #include "picture.h"
  30.  
  31. /*
  32.  * "Dither matrices" used to encode the 'number' of a ray that samples a
  33.  * particular portion of a pixel.  Hand-coding is ugly, but...
  34.  */
  35. static int        *SampleNumbers;
  36. static int OneSample[1] =     {0};
  37. static int TwoSamples[4] =    {0, 2,
  38.                  3, 1};
  39. static int ThreeSamples[9] =    {0, 2, 7,
  40.                  6, 5, 1,
  41.                  3, 8, 4};
  42. static int FourSamples[16] =    { 0,  8,  2, 10,
  43.                  12,  4, 14,  6,
  44.                   3, 11,  1,  9,
  45.                  15,  7, 13,  5};
  46. static int FiveSamples[25] =    { 0,  8, 23, 17,  2,
  47.                  19, 12,  4, 20, 15,
  48.                   3, 21, 16,  9,  6,
  49.                  14, 10, 24,  1, 13,
  50.                  22,  7, 18, 11,  5};
  51. static int SixSamples[36] =    { 6, 32,  3, 34, 35,  1,
  52.                   7, 11, 27, 28,  8, 30,
  53.                  24, 14, 16, 15, 23, 19,
  54.                  13, 20, 22, 21, 17, 18,
  55.                  25, 29, 10,  9, 26, 12,
  56.                  36,  5, 33,  4,  2, 31};
  57. static int SevenSamples[49] =    {22, 47, 16, 41, 10, 35,  4,
  58.                   5, 23, 48, 17, 42, 11, 29,
  59.                  30,  6, 24, 49, 18, 36, 12,
  60.                  13, 31,  7, 25, 43, 19, 37,
  61.                  38, 14, 32,  1, 26, 44, 20,
  62.                  21, 39,  8, 33,  2, 27, 45,
  63.                  46, 15, 40,  9, 34,  3, 28};
  64. static int EightSamples[64] =    { 8, 58, 59,  5,  4, 62, 63,  1,
  65.                  49, 15, 14, 52, 53, 11, 10, 56,
  66.                  41, 23, 22, 44, 45, 19, 18, 48,
  67.                  32, 34, 35, 29, 28, 38, 39, 25,
  68.                  40, 26, 27, 37, 36, 30, 31, 33,
  69.                  17, 47, 46, 20, 21, 43, 42, 24,
  70.                   9, 55, 54, 12, 13, 51, 50, 16,
  71.                  64,  2,  3, 61, 60,  6,  7, 57};
  72. #define RFAC    0.299
  73. #define GFAC    0.587
  74. #define BFAC    0.114
  75.  
  76. #define NOT_CLOSED 0
  77. #define CLOSED_PARTIAL   1
  78. #define CLOSED_SUPER 2
  79. /*
  80.  * If a region has area < MINAREA, it is considered to be "closed",
  81.  * (a permanent leaf).  Regions that meet this criterion
  82.  * are drawn pixel-by-pixel rather.
  83.  */
  84. #define MINAREA        9
  85.  
  86. #define SQ_AREA(s)    (((s)->xsize+1)*((s)->ysize+1))
  87.  
  88. #define PRIORITY(s)    ((s)->var * SQ_AREA(s))
  89.  
  90. #define INTENSITY(p)    ((RFAC*(p)[0] + GFAC*(p)[1] + BFAC*(p)[2])/255.)
  91.  
  92. #define OVERLAPS_RECT(s) (!Rectmode || \
  93.                 ((s)->xpos <= Rectx1 && \
  94.                  (s)->ypos <= Recty1 && \
  95.                  (s)->xpos+(s)->xsize >= Rectx0 && \
  96.                  (s)->ypos+(s)->ysize >= Recty0))
  97.  
  98. typedef unsigned char RGB[3];
  99.  
  100. static RGB **Image;
  101. static char **SampleMap;
  102.  
  103. /*
  104.  * Sample square
  105.  */
  106. typedef struct SSquare {
  107.     short xpos, ypos, xsize, ysize;
  108.     short depth;
  109.     short leaf, closed;
  110.     float mean, var, prio;
  111.     struct SSquare *child[4], *parent;
  112. } SSquare;
  113.  
  114. SSquare *SSquares, *SSquareCreate(), *SSquareInstall(), *SSquareSelect(),
  115.     *SSquareFetchAtMouse();
  116.  
  117. Float SSquareComputeLeafVar();
  118.  
  119. Ray    TopRay;                /* Top-level ray. */
  120. int    Rectmode = FALSE,
  121.     Rectx0, Recty0, Rectx1, Recty1;
  122. int    SuperSampleMode = 0;
  123. #define SSCLOSED (SuperSampleMode + 1)
  124.  
  125. Render(argc, argv)
  126. int argc;
  127. char **argv;
  128. {
  129.     /*
  130.      * Do an adaptive trace, displaying results in a
  131.      * window as we go.
  132.      */
  133.     SSquare *cursq;
  134.     Pixel *pixelbuf;
  135.     int y, x;
  136.  
  137.     /*
  138.      * The top-level ray TopRay always has as its origin the
  139.      * eye position and as its medium NULL, indicating that it
  140.      * is passing through a medium with index of refraction
  141.      * equal to DefIndex.
  142.      */
  143.     TopRay.pos = Camera.pos;
  144.     TopRay.media = (Medium *)0;
  145.     TopRay.depth = 0;
  146.     /*
  147.      * Doesn't handle motion blur yet.
  148.      */
  149.     TopRay.time = Options.framestart;
  150.  
  151.     GraphicsInit(Screen.xsize, Screen.ysize, "rayview");
  152.     /*
  153.      * Allocate array of samples.
  154.      */
  155.     Image=(RGB **)Malloc(Screen.ysize*sizeof(RGB *));
  156.     SampleMap = (char **)Malloc(Screen.ysize * sizeof(char *));
  157.     for (y = 0; y < Screen.ysize; y++) {
  158.         Image[y]=(RGB *)Calloc(Screen.xsize, sizeof(RGB));
  159.         SampleMap[y] = (char *)Calloc(Screen.xsize, sizeof(char));
  160.     }
  161.     switch (Sampling.sidesamples) {
  162.         case 1:
  163.             SampleNumbers = OneSample;
  164.             break;
  165.         case 2:
  166.             SampleNumbers = TwoSamples;
  167.             break;
  168.         case 3:
  169.             SampleNumbers = ThreeSamples;
  170.             break;
  171.         case 4:
  172.             SampleNumbers = FourSamples;
  173.             break;
  174.         case 5:
  175.             SampleNumbers = FiveSamples;
  176.             break;
  177.         case 6:
  178.             SampleNumbers = SixSamples;
  179.             break;
  180.         case 7:
  181.             SampleNumbers = SevenSamples;
  182.             break;
  183.         case 8:
  184.             SampleNumbers = EightSamples;
  185.             break;
  186.         default:
  187.             RLerror(RL_PANIC,
  188.                 "Sorry, %d rays/pixel not supported.\n",
  189.                     Sampling.totsamples);
  190.     }
  191.     /*
  192.      * Take initial four samples
  193.      */
  194.     SSquareSample(0, 0, FALSE);
  195.     SSquareSample(Screen.xsize -1, 0, FALSE);
  196.     SSquareSample(Screen.xsize -1, Screen.ysize -1, FALSE);
  197.     SSquareSample(0, Screen.ysize -1, FALSE);
  198.     SSquares = SSquareInstall(0, 0, Screen.xsize -1, Screen.ysize -1,
  199.                   0, (SSquare *) NULL);
  200.  
  201.     for (y = 1; y <= 5; y++) {
  202.         /*
  203.          * Create and draw every region at depth y.
  204.          */
  205.         SSquareDivideToDepth(SSquares, y);
  206.     }
  207.         
  208.  
  209.     while ((cursq = SSquareSelect(SSquares)) != (SSquare *)NULL) {
  210.         SSquareDivide(cursq);
  211.         if (GraphicsRedraw())
  212.             SSquareDraw(SSquares);
  213.         if (GraphicsMiddleMouseEvent()) 
  214.             SSetRectMode();
  215.     }
  216.  
  217.     /*
  218.      * Finished the image; write to image file.
  219.      */
  220.     pixelbuf = (Pixel *)Malloc(Screen.xsize * sizeof(Pixel));
  221.     PictureStart(argv);
  222.     for (y = 0; y < Screen.ysize; y++) {
  223.         /*
  224.          * This is really disgusting.
  225.          */
  226.         for (x = 0; x < Screen.xsize; x++) {
  227.             pixelbuf[x].r = Image[y][x][0] / 255.;
  228.             pixelbuf[x].g = Image[y][x][1] / 255.;
  229.             pixelbuf[x].b = Image[y][x][2] / 255.;
  230.             pixelbuf[x].alpha = SampleMap[y][x];
  231.         }
  232.         PictureWriteLine(pixelbuf);
  233.     }
  234.     PictureEnd();
  235.     free((voidstar)pixelbuf);
  236. }
  237.  
  238. Float
  239. SampleTime(sampnum)
  240. int sampnum;
  241. {
  242.     Float window, jitter = 0.0, res;
  243.  
  244.     if (Options.shutterspeed <= 0.)
  245.         return Options.framestart;
  246.     if (Options.jitter)
  247.         jitter = nrand();
  248.     window = Options.shutterspeed / Sampling.totsamples;
  249.     res = Options.framestart + window * (sampnum + jitter);
  250.     TimeSet(res);
  251.     return res;
  252. }
  253.  
  254. SSetRectMode()
  255. {
  256.     int x1,y1,x2,y2;
  257.  
  258.     if (Rectmode) {
  259.         Rectmode = FALSE;
  260.         RecomputePriority(SSquares);
  261.     }
  262.     GraphicsGetMousePos(&x1, &y1);
  263.     while (GraphicsMiddleMouseEvent())
  264.         ;
  265.     GraphicsGetMousePos(&x2, &y2);
  266.     if (x1 < x2) {
  267.         Rectx0 = (x1 < 0) ? 0 : x1;
  268.         Rectx1 = (x2 >= Screen.xsize) ? Screen.xsize - 1 : x2;
  269.     } else {
  270.         Rectx0 = (x2 < 0) ? 0 : x2;
  271.         Rectx1 = (x1 >= Screen.xsize) ? Screen.xsize - 1 : x1;
  272.     } if (y1 < y2) {
  273.         Recty0 = (y1 < 0) ? 0 : y1;
  274.         Recty1 = (y2 >= Screen.ysize) ? Screen.ysize - 1 : y2;
  275.     } else {
  276.         Recty0 = (y2 < 0) ? 0 : y2;
  277.         Recty1 = (y1 >= Screen.ysize) ? Screen.ysize - 1 : y1;
  278.     }
  279.     Rectmode = TRUE;
  280.     /* setup current rect */
  281.     (void)RecomputePriority(SSquares);
  282. }
  283.  
  284. RecomputePriority(sq)
  285. SSquare *sq;
  286. {
  287.     Float maxp;
  288.  
  289.     if (!OVERLAPS_RECT(sq)) {
  290.         sq->closed = SSCLOSED;
  291.         return FALSE;
  292.     }
  293.  
  294.     if (sq->leaf) {
  295.         if (SQ_AREA(sq) >= MINAREA)
  296.             sq->closed = NOT_CLOSED;
  297.         return TRUE;
  298.     }
  299.     maxp = 0.;
  300.     if (RecomputePriority(sq->child[0]))
  301.         maxp = max(maxp, sq->child[0]->prio);
  302.     if (RecomputePriority(sq->child[1]))
  303.         maxp = max(maxp, sq->child[1]->prio);
  304.     if (RecomputePriority(sq->child[2]))
  305.         maxp = max(maxp, sq->child[2]->prio);
  306.     if (RecomputePriority(sq->child[3]))
  307.         maxp = max(maxp, sq->child[3]->prio);
  308.     sq->prio = maxp;
  309. #if 0
  310.     if ((sq->child[0]->closed == CLOSED_SUPER) &&
  311.         (sq->child[1]->closed == CLOSED_SUPER) &&
  312.         (sq->child[2]->closed == CLOSED_SUPER) &&
  313.         (sq->child[3]->closed == CLOSED_SUPER))
  314.         sq->closed = CLOSED_SUPER;
  315.     else if (sq->child[0]->closed && sq->child[1]->closed &&
  316.          sq->child[2]->closed && sq->child[3]->closed)
  317.         sq->closed = CLOSED_PARTIAL;
  318.     else
  319.         sq->closed = NOT_CLOSED;
  320. #else
  321.     if ((sq->child[0]->closed >= SSCLOSED) &&
  322.         (sq->child[1]->closed >= SSCLOSED) &&
  323.         (sq->child[2]->closed >= SSCLOSED) &&
  324.         (sq->child[3]->closed >= SSCLOSED))
  325.         sq->closed = SSCLOSED;
  326.     else
  327.         sq->closed = NOT_CLOSED;
  328. #endif
  329.     return TRUE;
  330. }
  331.  
  332. SSquareSample(x, y, supersample)
  333. int x, y, supersample;
  334. {
  335.     Float upos, vpos, u, v;
  336.     int xx, yy, xp, sampnum, usamp, vsamp;
  337.     Pixel ctmp;
  338.     Pixel p;
  339.     extern unsigned char correct();
  340.  
  341.     if (SampleMap[y][x] >= 128 + supersample)
  342.         /* already a sample there */
  343.         return;
  344.     SampleMap[y][x] = 128 + supersample;
  345.     if (supersample) {
  346.         p.r = p.g = p.b = p.alpha = 0;
  347.         sampnum = 0;
  348.         xp = x + Screen.minx;
  349.         vpos = Screen.miny + y - 0.5*Sampling.filterwidth;
  350.         for (yy = 0; yy < Sampling.sidesamples; yy++,
  351.              vpos += Sampling.filterdelta) {
  352.             upos = xp - 0.5*Sampling.filterwidth;
  353.             for (xx = 0; xx < Sampling.sidesamples; xx++,
  354.                  upos += Sampling.filterdelta) {
  355.                 if (Options.jitter) {
  356.                     u = upos + nrand()*Sampling.filterdelta;
  357.                     v = vpos + nrand()*Sampling.filterdelta;
  358.                 } else {
  359.                     u = upos;
  360.                     v = vpos;
  361.                 }
  362.                 TopRay.time = SampleTime(SampleNumbers[sampnum]);
  363.                 SampleScreen(u, v, &TopRay, &ctmp,
  364.                          SampleNumbers[sampnum]);
  365.                 p.r += ctmp.r*Sampling.filter[xx][yy];
  366.                 p.g += ctmp.g*Sampling.filter[xx][yy];
  367.                 p.b += ctmp.b*Sampling.filter[xx][yy];
  368.                 if (++sampnum == Sampling.totsamples)
  369.                     sampnum = 0;
  370.             }
  371.         }
  372.     }
  373.     else {
  374.         sampnum = nrand() * Sampling.totsamples;
  375.         usamp = sampnum % Sampling.sidesamples;
  376.         vsamp = sampnum / Sampling.sidesamples;
  377.  
  378.         vpos = Screen.miny + y - 0.5*Sampling.filterwidth
  379.             + vsamp * Sampling.filterdelta;
  380.         upos = x + Screen.minx - 0.5*Sampling.filterwidth +
  381.                 usamp*Sampling.filterdelta;
  382.         if (Options.jitter) {
  383.             vpos += nrand()*Sampling.filterdelta;
  384.             upos += nrand()*Sampling.filterdelta;
  385.         }
  386.         TopRay.time = SampleTime(SampleNumbers[sampnum]);
  387.         SampleScreen(upos, vpos, &TopRay, &p, SampleNumbers[sampnum]);
  388.     }
  389.     Image[y][x][0] = CORRECT(p.r);
  390.     Image[y][x][1] = CORRECT(p.g);
  391.     Image[y][x][2] = CORRECT(p.b);
  392. }
  393.  
  394. SSquare *
  395. SSquareCreate(xp, yp, xs, ys, d, parent)
  396. int xp, yp, xs, ys, d;
  397. SSquare *parent;
  398. {
  399.     SSquare *new;
  400.     Float i1, i2, i3, i4;
  401.  
  402.     new = (SSquare *)Calloc(1, sizeof(SSquare));
  403.     new->xpos = xp; new->ypos = yp;
  404.     new->xsize = xs; new->ysize = ys;
  405.     new->depth = d;
  406.     new->parent = parent;
  407.     i1 = INTENSITY(Image[new->ypos][new->xpos]);
  408.     i2 = INTENSITY(Image[new->ypos+new->ysize][new->xpos]);
  409.     i3 = INTENSITY(Image[new->ypos+new->ysize][new->xpos+new->xsize]);
  410.     i4 = INTENSITY(Image[new->ypos][new->xpos+new->xsize]);
  411.     new->mean = 0.25 * (i1+i2+i3+i4);
  412.     if (SQ_AREA(new) < MINAREA) {
  413.         new->prio = 0;
  414.         new->closed = SSCLOSED;
  415.     } else {
  416.         new->var = SSquareComputeLeafVar(new, i1, i2, i3, i4);
  417.         new->prio = PRIORITY(new);
  418.         new->closed = NOT_CLOSED;
  419.     }
  420.     new->leaf = TRUE;
  421.     return new;
  422. }
  423.  
  424. Float
  425. SSquareComputeLeafVar(sq, i1, i2, i3, i4)
  426. SSquare *sq;
  427. Float i1, i2, i3, i4;
  428. {
  429.     Float res, diff;
  430.  
  431.     diff = i1 - sq->mean;
  432.     res = diff*diff;
  433.     diff = i2 - sq->mean;
  434.     res += diff*diff;
  435.     diff = i3 - sq->mean;
  436.     res += diff*diff;
  437.     diff = i4 - sq->mean;
  438.     return res + diff*diff;
  439. }
  440.  
  441. SSquareDivideToDepth(sq, d)
  442. SSquare *sq;
  443. int d;
  444. {
  445.     if (sq->depth == d)
  446.         return;
  447.     if (sq->leaf)
  448.         SSquareDivide(sq);
  449.     SSquareDivideToDepth(sq->child[0], d);
  450.     SSquareDivideToDepth(sq->child[1], d);
  451.     SSquareDivideToDepth(sq->child[2], d);
  452.     SSquareDivideToDepth(sq->child[3], d);
  453. }
  454.  
  455. SSquareDivide(sq)
  456. SSquare *sq;
  457. {
  458.     int lowx, lowy, midx, midy, hix, hiy;
  459.     int newxsize, newysize, ndepth, supersample;
  460.     /*
  461.      * Divide the square into fourths by tracing 12
  462.      * new samples if necessary.
  463.      */
  464.     newxsize = sq->xsize / 2;
  465.     newysize = sq->ysize / 2;
  466.     lowx = sq->xpos; lowy = sq->ypos;
  467.     midx = sq->xpos + newxsize;
  468.     midy = sq->ypos + newysize;
  469.     hix  = sq->xpos + sq->xsize;
  470.     hiy  = sq->ypos + sq->ysize;
  471.     ndepth = sq->depth + 1;
  472.     /* create new samples */
  473.     supersample = FALSE;
  474.     SSquareSample(midx, lowy, supersample);
  475.     SSquareSample(lowx, midy, supersample);
  476.     SSquareSample(midx, midy, supersample);
  477.     SSquareSample(hix,  midy, supersample);
  478.     SSquareSample(midx, hiy, supersample);
  479. #ifdef SHARED_EDGES
  480.     /* create and draw new squares */
  481.     sq->child[0] = SSquareInstall(lowx,lowy,newxsize,newysize,ndepth,sq);
  482.     sq->child[1] = SSquareInstall(midx, lowy, sq->xsize - newxsize,
  483.             newysize, ndepth,sq);
  484.     sq->child[2] = SSquareInstall(lowx, midy, newxsize,
  485.             sq->ysize - newysize, ndepth,sq);
  486.     sq->child[3] = SSquareInstall(midx, midy, sq->xsize - newxsize,
  487.              sq->ysize - newysize, ndepth,sq);
  488. #else
  489.     /*
  490.      *  draw additional samples in order to subdivide such that
  491.      * edges of regions do not overlap
  492.      */
  493.     SSquareSample(midx +1, lowy, supersample);
  494.     SSquareSample(midx +1, midy, supersample);
  495.     SSquareSample(lowx, midy +1, supersample);
  496.     SSquareSample(midx, midy +1, supersample);
  497.     SSquareSample(midx +1, midy +1, supersample);
  498.     SSquareSample(hix, midy +1, supersample);
  499.     SSquareSample(midx +1, hiy, supersample);
  500.  
  501.     /* create and draw new squares */
  502.     sq->child[0] = SSquareInstall(lowx,lowy,
  503.                 newxsize,newysize,ndepth,sq);
  504.     sq->child[1] = SSquareInstall(midx+1, lowy, sq->xsize - newxsize -1,
  505.             newysize, ndepth,sq);
  506.     sq->child[2] = SSquareInstall(lowx, midy+1, newxsize,
  507.             sq->ysize - newysize-1, ndepth,sq);
  508.     sq->child[3] = SSquareInstall(midx+1, midy+1, sq->xsize - newxsize-1,
  509.              sq->ysize - newysize-1, ndepth,sq);
  510. #endif
  511.     sq->leaf = FALSE;
  512.     /*
  513.      * Recompute parent's mean and variance.
  514.      */
  515.     if (OVERLAPS_RECT(sq))
  516.         SSquareRecomputeStats(sq);
  517. }
  518.  
  519. SSquareRecomputeStats(sq)
  520. SSquare *sq;
  521. {
  522.     Float maxp;
  523.     int in[4], closeflag;
  524.  
  525.     in[0] = OVERLAPS_RECT(sq->child[0]);
  526.     in[1] = OVERLAPS_RECT(sq->child[1]);
  527.     in[2] = OVERLAPS_RECT(sq->child[2]);
  528.     in[3] = OVERLAPS_RECT(sq->child[3]);
  529.  
  530.     if ((in[0] && (sq->child[0]->closed < SSCLOSED)) ||
  531.         (in[1] && (sq->child[1]->closed < SSCLOSED)) ||
  532.         (in[2] && (sq->child[2]->closed < SSCLOSED)) ||
  533.         (in[3] && (sq->child[3]->closed < SSCLOSED))) {
  534.         maxp = 0.;
  535.         if (in[0])
  536.             maxp = max(maxp, sq->child[0]->prio);
  537.         if (in[1])
  538.             maxp = max(maxp, sq->child[1]->prio);
  539.         if (in[2])
  540.             maxp = max(maxp, sq->child[2]->prio);
  541.         if (in[3])
  542.             maxp = max(maxp, sq->child[3]->prio);
  543.         sq->closed = NOT_CLOSED;
  544.         sq->prio = maxp;
  545.     } else if ((sq->child[0]->closed == CLOSED_SUPER) &&
  546.            (sq->child[1]->closed == CLOSED_SUPER) &&
  547.            (sq->child[2]->closed == CLOSED_SUPER) &&
  548.            (sq->child[3]->closed == CLOSED_SUPER)) {
  549.         sq->closed = CLOSED_SUPER;
  550.         sq->prio = 0;
  551. #if 0
  552.     } else if ((!in[0] || sq->child[0]->closed >= SSCLOSED) &&
  553.            (!in[1] || sq->child[1]->closed >= SSCLOSED) &&
  554.            (!in[2] || sq->child[2]->closed >= SSCLOSED) &&
  555.            (!in[3] || sq->child[3]->closed >= SSCLOSED)) {
  556.         sq->closed = SSCLOSED;
  557.         sq->prio = 0;
  558. #endif
  559.     } else {
  560.         sq->closed = SSCLOSED;
  561.         sq->prio = 0;
  562.     }
  563.     if (sq->parent)
  564.         SSquareRecomputeStats(sq->parent);
  565. }
  566.  
  567. SSquare *
  568. SSquareInstall(xp, yp, xs, ys, d, parent)
  569. int xp, yp, xs, ys, d;
  570. SSquare *parent;
  571. {
  572.     SSquare *new;
  573.  
  574.     new = SSquareCreate(xp, yp, xs, ys, d, parent);
  575.     SSquareDraw(new);
  576.     return new;
  577. }
  578.  
  579. SSquare *
  580. SSquareSelect(list)
  581. SSquare *list;
  582. {
  583.     int i;
  584.     SSquare *res, *which;
  585.  
  586.     /*
  587.      * If mousebutton is pressed,
  588.      * find the square in which the mouse is located and
  589.      * return that if not a leaf (pixel-sized square).
  590.      */
  591.     if (GraphicsLeftMouseEvent()) {
  592.         SuperSampleMode = 0;
  593.         if ((res = SSquareFetchAtMouse(list)) != (SSquare *)NULL)
  594.             return res;
  595.     }
  596.     else if (GraphicsRightMouseEvent()) {
  597.         SuperSampleMode = 1;
  598.         if ((res = SSquareFetchAtMouse(list)) != (SSquare *)NULL) {
  599.             return res;
  600.         }
  601.     }
  602.     if (list->closed >= SSCLOSED) {
  603.         if (Rectmode) {
  604.             Rectmode = FALSE;
  605.             RecomputePriority(SSquares);
  606.             return SSquareSelect(list);
  607.         }
  608.         return (SSquare *)NULL;
  609.     }
  610.     /*
  611.      * Otherwise, find the square with the greatest
  612.      * 'priority'.
  613.      */
  614.     res = list;
  615.     while (res && !res->leaf) {
  616.         which = (SSquare *)NULL;
  617.         for (i = 0; i < 4; i++) {
  618.             if ((res->child[i]->closed < SSCLOSED) &&
  619.                 OVERLAPS_RECT(res->child[i])) {
  620.                 which = res->child[i];
  621.                 break;
  622.             }
  623.         }
  624.         while (++i < 4) {
  625.             if ((res->child[i]->closed < SSCLOSED) &&
  626.                 which->prio < res->child[i]->prio &&
  627.                 OVERLAPS_RECT(res->child[i]))
  628.                 which = res->child[i];
  629.         }
  630.         res = which;
  631.     }
  632.     return res;
  633. }
  634.  
  635. SSquare *
  636. SSquareFetchAtMouse(list)
  637. SSquare *list;
  638. {
  639.     SSquare *res;
  640.     int x, y;
  641.  
  642.     /*
  643.      * Get mouse position.
  644.      */
  645.     GraphicsGetMousePos(&x, &y);
  646.     res = list;
  647.     while (!res->leaf && (res->closed < SSCLOSED)) { 
  648.         /*
  649.          * Find in which child the mouse is located.
  650.          */
  651.         if (x < res->child[1]->xpos) {
  652.             if (y < res->child[2]->ypos)
  653.                 res = res->child[0];
  654.             else
  655.                 res = res->child[2];
  656.         } else if (y < res->child[3]->ypos)
  657.             res = res->child[1];
  658.         else
  659.             res = res->child[3];
  660.     }
  661.     if (res->closed >= SSCLOSED)
  662.         return (SSquare *)NULL;
  663.     return res;
  664. }
  665.  
  666. SSquareDraw(sq)
  667. SSquare *sq;
  668. {
  669.     if (SQ_AREA(sq) >= MINAREA)
  670.         GraphicsDrawRectangle(sq->xpos, sq->ypos, sq->xsize, sq->ysize,
  671.             Image[sq->ypos][sq->xpos],
  672.             Image[sq->ypos][sq->xpos+sq->xsize],
  673.             Image[sq->ypos+sq->ysize][sq->xpos+sq->xsize],
  674.             Image[sq->ypos+sq->ysize][sq->xpos]);
  675.     else
  676.         DrawPixels(sq->xpos, sq->ypos, sq->xsize, sq->ysize);
  677.     if (!sq->leaf) {
  678.         SSquareDraw(sq->child[0]);
  679.         SSquareDraw(sq->child[1]);
  680.         SSquareDraw(sq->child[2]);
  681.         SSquareDraw(sq->child[3]);
  682.     }
  683. }
  684.  
  685. DrawPixels(xp, yp, xs, ys)
  686. int xp, yp, xs, ys;
  687. {
  688.     int x, y, xi, yi;
  689.  
  690.     yi = yp;
  691.     for (y = 0; y <= ys; y++, yi++) {
  692.         xi = xp;
  693.         for (x = 0; x <= xs; x++, xi++) {
  694.             SSquareSample(xi, yi, SuperSampleMode);
  695.             GraphicsDrawPixel(xi, yi, Image[yi][xi]);
  696.         }
  697.     }
  698. }
  699.